﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using Library;
using CommandType = Library.CommandType;
using System.Threading;
namespace Server_XiLat
{
    public partial class ServerFrm : Form
    {
        private List<ClientComputer> _clients;
        private Socket _serverSocket;
        private byte[] _buffer;
        private List<int> list;
        public ServerFrm()
        {
            InitializeComponent();

            CheckForIllegalCrossThreadCalls = false;
            _clients = new List<ClientComputer>();
            _buffer = new byte[1024];
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _serverSocket = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);
            _serverSocket.Bind(new IPEndPoint(IPAddress.Any, 5555));
            _serverSocket.Listen(-1);

            txtLog.AppendText("Server đã khởi động và đang chờ kết nối\r\n");

            var asyncResult = _serverSocket.BeginAccept(OnClientAccepted, null);
            list = new List<int>();
            for (int i = 0; i <52; i++)
                list.Add(i);
        }

        private void OnClientAccepted(IAsyncResult ar)
        {
            try
            {
                // Lấy socket để liên lạc với client
                var client = _serverSocket.EndAccept(ar);

                txtLog.AppendText(
                    string.Format("Client {0} đã kết nối vào server {1}", 
                    client.RemoteEndPoint, "\r\n"));

                // Bắt đầu chấp nhận kết nối mới
                _serverSocket.BeginAccept(OnClientAccepted, null);

                var computer = new ClientComputer() { 
                        Connector=client,
                        UserName=string.Empty,
                        buffer=new byte[1024]
                };

                // Bắt đầu nhận dữ liệu


                client.BeginReceive(computer.buffer, 0,
                                       computer.buffer.Length,
                                       SocketFlags.None, 
                                       OnMessageReceived,
                                       computer);
            }
            catch (Exception ex)
            {
                txtLog.AppendText(ex.Message + "\r\n");
            }
        }

        private void OnMessageReceived(IAsyncResult ar)
        {
            try
            {
                var computer = ar.AsyncState as ClientComputer;
                computer.Connector.EndReceive(ar);
                var recvMsg = new ChatMessage(computer.buffer);
                txtLog.AppendText(string.Format("{0}: {1}",
                    recvMsg.SenderName, recvMsg.MsgBody));

                switch (recvMsg.CmdType)
                {
       
                    case CommandType.ClientLogin:
                        computer.UserName = recvMsg.SenderName;
                         var  cliensss = _clients.FindAll(x => x.UserName == computer.UserName);
                         if (cliensss.Count > 0)
                         {
                             recvMsg.MsgBody = "ten login trung cmnr";
                             recvMsg.CmdType = CommandType.Message;
                             var buffer1 = recvMsg.ToByteArray();
                             computer.Connector.BeginSend(buffer1, 0, buffer1.Length,
                                 SocketFlags.None, OnMessageSent, computer);
                         }
                         else
                         {
                             recvMsg.MsgBody = "ok";
                             recvMsg.CmdType = CommandType.Message;
                             var buffer1 = recvMsg.ToByteArray();
                             computer.Connector.BeginSend(buffer1, 0, buffer1.Length,
                                 SocketFlags.None, OnMessageSent, computer);
                             //Thread.Sleep(200);
                             _clients.Add(computer);
                             if (_clients.Count-1 == 0)
                             {
                                 recvMsg = new ChatMessage()
                                 {
                                     CmdType = CommandType.ChuRoom,
                                     SenderName = computer.UserName,
                                     MsgBody = ""
                                 };
                                 computer.TruongPhong = true;
                                 computer.SanSang = true;
                                 buffer1 = recvMsg.ToByteArray();
                                 computer.Connector.BeginSend(buffer1, 0, buffer1.Length,
                                 SocketFlags.None, OnMessageSent, computer);
                             }
                             else
                             {
                                 // Tính Thêm Phần Login người Chơi
                                 recvMsg = new ChatMessage(computer.buffer);
                                 BroadcastMessage(computer, recvMsg);
                                 BroadcastMessageLogin(computer, recvMsg);
                             }
                             
                         }
                        //_clients.Add(computer);
                        break;
                    case CommandType.Message:
                        BroadcastMessage(computer,recvMsg);
                        break;
                    case CommandType.ClientOut:
                        var idx = _clients.Remove(computer);
                        computer.Connector.Close(1000);
                        BroadcastMessage(computer, recvMsg);
                        break;
                   
                    case CommandType.BocBai:
                        var msg = new ChatMessage();
                        if (kiemtra(computer.QuanBai) > 21)
                        {
                            msg = new ChatMessage()
                            {
                                SenderName = recvMsg.SenderName,
                                CmdType = CommandType.BocBai,
                                MsgBody = "No"

                            };
                            var buffer = msg.ToByteArray();
                            computer.Connector.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, OnMessageSent, computer);
                        }
                        else
                        {
                            Random rd = new Random();
                            int bd = list[rd.Next(0, list.Count)];
                            msg = new ChatMessage()
                            {
                                SenderName = recvMsg.SenderName,
                                CmdType = CommandType.BocBai,
                                MsgBody = bd.ToString()

                            };
                            computer.QuanBai.Add(bd);
                            var buffer = msg.ToByteArray();
                            computer.Connector.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, OnMessageSent, computer);
                            msg.MsgBody = "";
                            BroadcastMessage(computer, msg);
                        }
                        
                        break;
                    case CommandType.PhatBai:
                        this.PhatBai();
                        var msg_2 = new ChatMessage()
                        {
                            SenderName = _clients[1].UserName,
                            CmdType = CommandType.ToiLuot,
                            MsgBody = ""
                        };
                        var buffer_1 = msg_2.ToByteArray();
                        _clients[1].ToiLuoc = true;
                        _clients[1].Connector.BeginSend(buffer_1, 0, buffer_1.Length, SocketFlags.None, OnMessageSent, _clients[1]);
                        //Thread.Sleep(200);
                        foreach (var _computer in _clients)
                        {
                            if (_computer != _clients[1])
                            {
                                _computer.ToiLuoc = false;
                            }
                        }
                        BroadcastMessage(_clients[1], msg_2);
                        break;
                    case CommandType.SanSang:
                        computer.SanSang = true;
                        
                            var msg2 = new ChatMessage()
                            {
                                CmdType = CommandType.SanSang,
                                SenderName = computer.UserName,
                                MsgBody = ""
                            };
                            BroadcastMessage(computer, msg2);
                            if (kiemtrass())
                            {
                                msg2 = new ChatMessage()
                                {
                                    CmdType = CommandType.PhatBai,
                                    SenderName = "",
                                    MsgBody = ""
                                };
                                BroadcastMessagePhatBai(computer, msg2);
                            }
                        break;
                    case CommandType.Boqua:

                        var luotclient = _clients.FindLast(x => !x.ToiLuoc);
                        if (luotclient != null)
                        {
                            msg2 = new ChatMessage()
                            {
                                CmdType = CommandType.ToiLuot,
                                SenderName = luotclient.UserName,
                                MsgBody = ""
                            };
                            luotclient.ToiLuoc = true;
                            if (luotclient.TruongPhong)
                            {
                                msg2.MsgBody = "TruongPhong";
                            }
                            var buffer3 = msg2.ToByteArray();
                            luotclient.Connector.BeginSend(buffer3, 0, buffer3.Length,
                        SocketFlags.None, OnMessageSent, luotclient);
                            BroadcastMessage(luotclient, msg2);
                        }
                        else
                        {
                            var clientChuPhong = _clients.Find(x => x.TruongPhong);
                            msg2 = new ChatMessage()
                            {
                                CmdType = CommandType.BatDauChoi,
                                SenderName = clientChuPhong.UserName,
                                MsgBody = "BatDau"
                            };
                            
                            var buffer3 = msg2.ToByteArray();
                            clientChuPhong.Connector.BeginSend(buffer3, 0, buffer3.Length,
                            SocketFlags.None, OnMessageSent, clientChuPhong);
                            BroadcastMessage(clientChuPhong, msg2);
                        }
                        
                        break;
                    case CommandType.MoBai:
                        var cl = _clients.Find(x => x.UserName == recvMsg.SenderName);
                        string s1 ="",s2="" ;
                        int t1=0,t2=0;
                        #region Lấy Bài So Sanh
                        foreach (var qb in cl.QuanBai)
                        {
                            if ((cl.QuanBai.Count == 2 && int.Parse(imageList1.Images.Keys[qb].ToString().Split('_')[0]) == 1) || (cl.QuanBai.Count == 3 && kiemtra(cl.QuanBai) <= 10))
                                t1 += 10 + int.Parse(imageList1.Images.Keys[qb].ToString().Split('_')[0]);
                            else
                            {
                                s1 += qb.ToString() + " ";
                                t1 += int.Parse(imageList1.Images.Keys[qb].ToString().Split('_')[0]);
                            }
                        }
                        var cl1 = _clients.Find(x => x.TruongPhong);
                        foreach (var qb in cl1.QuanBai)
                        {
                            if ((cl1.QuanBai.Count == 2 && int.Parse(imageList1.Images.Keys[qb].ToString().Split('_')[0]) == 1) || (cl1.QuanBai.Count == 3 && kiemtra(cl.QuanBai) <= 10))
                                t1 += 10 + int.Parse(imageList1.Images.Keys[qb].ToString().Split('_')[0]);
                            else
                            {
                                s2 += qb.ToString() + " ";
                                t2 += int.Parse(imageList1.Images.Keys[qb].ToString().Split('_')[0]);
                            }
                        }
                        #endregion
                        msg2 = new ChatMessage()
                        {
                            CmdType = CommandType.MoBai,
                            SenderName = cl.UserName,
                            MsgBody = s1
                        };
                        var msg3 = new ChatMessage()
                        {
                            CmdType = CommandType.MoBai,
                            SenderName = cl1.UserName,
                            MsgBody = s2
                        };
                        sosanh(msg2, msg3, t1, t2, cl1, cl);
                        var buffer4 = msg2.ToByteArray();
                        string a = Encoding.ASCII.GetString(buffer4);
                        BroadcastMessage(cl, msg2);

                        buffer4 = msg3.ToByteArray();
                        cl.Connector.BeginSend(buffer4, 0, buffer4.Length,
                            SocketFlags.None, OnMessageSent, cl);

                        
                        break;
                    
                    
                    
                }

                if (recvMsg.CmdType != CommandType.ClientOut)
                {
                    computer.ResetBuffer();
                    computer.Connector.BeginReceive(computer.buffer, 0, computer.buffer.Length,
                                        SocketFlags.None,
                                        OnMessageReceived, computer);
                }
            }
            catch (Exception ex)
            {
          
                txtLog.AppendText(ex.Message + "\r\n");
            }
        }
        #region So Sanh
        private void sosanh(ChatMessage msg2, ChatMessage msg3, int t1, int t2,ClientComputer cl1,ClientComputer cl)
        {
            if (((t2 < 21 && t1 < 21) && t2 > t1 && t1 != 2 && xilac(cl.QuanBai)) || (t2 <= 21 && t1 > 21) || (t2 == 2 && t1 != 2) || (xilac(cl1.QuanBai) && !xilac(cl.QuanBai)))
            {
                msg2.MsgBody += "/" + cl1.UserName + " Thắng " + cl.UserName + " ^^";
                msg3.MsgBody += "/" + cl1.UserName + " Thắng " + cl.UserName + " ^^";
            }
            else if (t2 == t1 || (t2 > 21 && t1 > 21) || (t2 == 2 && t1 == 2) || (xilac(cl1.QuanBai) && xilac(cl.QuanBai)))
            {
                msg2.MsgBody += "/" + cl1.UserName + " Huề " + cl.UserName + " ^^";
                msg3.MsgBody += "/" + cl1.UserName + " Huề " + cl.UserName + " ^^";
            }
            else
            {
                msg2.MsgBody += "/" + cl1.UserName + " Thua " + cl.UserName + " ^^";
                msg3.MsgBody += "/" + cl1.UserName + " Thua " + cl.UserName + " ^^";
            }
        }
        private bool xilac(List<int> cl)
        {
            if(cl.Count ==2 && (int.Parse(imageList1.Images.Keys[0].ToString().Split('_')[0])==1||int.Parse(imageList1.Images.Keys[1].ToString().Split('_')[0])==1))
            {
                if((int.Parse(imageList1.Images.Keys[0].ToString().Split('_')[0])+(int.Parse(imageList1.Images.Keys[0].ToString().Split('_')[0])))==11)
                {
                    return true;
                }
            }
            return false;
        }
        private int kiemtra(List<int> cl)
        {
            int tong = 0;
            foreach (var t in cl)
            {
                tong += int.Parse(imageList1.Images.Keys[t].ToString().Split('_')[0]);
            }
            return tong;
        }
        #endregion
        private void ToiLuotSend()
        {
            ClientComputer clien1 = new ClientComputer();
            //string a = clien1.UserName;
            clien1 = _clients.Find(x=>!x.ToiLuoc&&!x.TruongPhong);
            if (clien1 == null)
            {
                clien1 = _clients.Find(x => !x.ToiLuoc);
            }
            if (clien1 != null)
            {
                var msg2 = new ChatMessage()
                {
                    CmdType = CommandType.ToiLuot,
                    SenderName = clien1.UserName,
                    MsgBody = ""
                };
                var buffer = msg2.ToByteArray();

                clien1.Connector.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, OnMessageSent, clien1);
                clien1.ToiLuoc = true;
                //Thread.Sleep(200);
                BroadcastMessage(clien1, msg2);
            }
        }
        private bool kiemtrass()
        {
            int count =0;
            foreach (var computer in _clients)
            {
                if (computer.SanSang == true)
                {
                    count++;
                }
            }
            if (count == _clients.Count)
                return true;
            return false;
        }
        private void PhatBai()
        {
            Random rd1 = new Random();
            int[] bai = new int[2];
            foreach (var computer in _clients)
            {
                for (int i = 0; i < 2; i++)
                {
                    bai[i] = list[rd1.Next(0, list.Count-1)];
                    //list.RemoveAt(bai[i]);
                    computer.QuanBai.Add(bai[i]);
                    list.Remove(bai[i]);
                }

                var msg1 = new ChatMessage()
                {
                    SenderName = computer.UserName,
                    CmdType = CommandType.PhatBai,
                    MsgBody = bai[0].ToString() + " " + bai[1].ToString()

                };
                
                var buffer_1 = msg1.ToByteArray();
                computer.Connector.BeginSend(buffer_1, 0, buffer_1.Length,
                        SocketFlags.None, OnMessageSent, computer);
                Thread.Sleep(500);
            }
        }
        private void BroadcastMessage(ClientComputer client,ChatMessage recvMsg)
        {
            foreach (var computer in _clients)
            {
                 if(computer != client)
                {
                    var buffer = recvMsg.ToByteArray();
                    
                    computer.Connector.BeginSend(buffer, 0, buffer.Length,
                        SocketFlags.None, OnMessageSent, computer);
                    Thread.Sleep(200);
                }
            }
            
        }
        private void BroadcastMessagePhatBai(ClientComputer client, ChatMessage recvMsg)
        {
            foreach (var computer in _clients)
            {
                if (computer != client && computer.TruongPhong == true)
                {
                    var buffer = recvMsg.ToByteArray();
                    computer.Connector.BeginSend(buffer, 0, buffer.Length,
                        SocketFlags.None, OnMessageSent, computer);
                }
            }

        }
        private void BroadcastMessageLogin(ClientComputer client, ChatMessage recvMsg)
        {
            if (_clients.Count > 1)
            {
                foreach (var computer in _clients)
                {
                    if (computer != client && computer.TruongPhong == true)
                    {
                        var msg = new ChatMessage()
                        {
                            CmdType = CommandType.ClientLogin,
                            SenderName = computer.UserName,
                            MsgBody = "TruongPhong"

                        };
                        var buffer = msg.ToByteArray();
                        client.Connector.BeginSend(buffer, 0, buffer.Length,
                            SocketFlags.None, OnMessageSent, client);
                        Thread.Sleep(500);

                    }
                    else if (computer != client)
                    {
                        var msg = new ChatMessage()
                        {
                            CmdType = CommandType.ClientLogin,
                            SenderName = computer.UserName,
                            MsgBody = "login"

                        };
                        var buffer = msg.ToByteArray();
                        
                        client.Connector.BeginSend(buffer, 0, buffer.Length,
                            SocketFlags.None, OnMessageSent, client);
                        Thread.Sleep(500);
                        
                    }
                }
            }

        }
        private void OnMessageSent(IAsyncResult ar)
        {
            try
            {
                var computer = ar.AsyncState as ClientComputer;
                computer.Connector.EndSend(ar);
            }
            catch (Exception ex)
            {
                txtLog.AppendText(ex.Message + "\r\n");
            }
        }
    }
}
